package kt01

fun main() {
    //函数的声明 用lambda去描述函数的声明
    var method1: () -> Unit

    var method2: (Int, Int) -> Unit

    var method3: (String, Double) -> Any

    var method4: (Int, Double, Long, String) -> Boolean

    var method5: (Int, Int) -> Int

    //函数的声明 +函数的实现

    val method01 = { println("我是method01函数") }
    method01()
    method01.invoke()

    val method02 = { println("我是method02函数") }
    println(method02())

    val method03 = { str: String -> println("你传递进来的值是：$str") }
    method03("1234")

    val method04 = { number1: Int, number2: Int -> number1.toString() + number2.toString() }
    println(method04(1, 2))

    val method05 = { number1: Int, number2: Int -> number1 + number2 }
    println(method05(1, 2))

    val method06: (Int) -> String //先声明
    method06 = fun(value: Int): String = value.toString() //后实现
    println(method06(99))

    //用先声明的类型，来自动推断
    val method07: (Int) -> String //先声明
    method07 = fun(value) = value.toString() //后实现
    println(method07(99))
    //    声明+实现 一气呵成
    val method08: (Int) -> String /*左边是声明*/ = { value -> "$value aaa" }/*右边是实现*/
    println(method08(77))

    val method10: (String) -> Unit = {
        println("你传递进来的值 是$it")
    }
    method10("李元霸")

    val method11: (Int) -> Unit = {
        when (it) {
            1 -> println("你传递的是1")
            in 20..60 -> println("你传递的是20~60之间的数字")
            else -> println("都不满足")
        }
    }
    method11(50)

    val method12: (Int, Int) -> Unit = { _, number2 ->
        println("你传递的第二个参数是：$number2")

    }
    method12.invoke(100, 200)

    val method14 = { str: Any -> str }
    println(method14(true))
    println(method14(54.45f))

    val method15 = { sex: Char ->
        if (sex == '男') println("男") else println("女")
    }
    method15('男')

    var method16 /*: (Int)->Unit */ = { number: Int -> println("你的值是$number") }
    //虽然你覆盖了，类型还是（Int）->Unit
    method16 = { println("???你的值 是什么$it") }

    method16(888)
    val method17 = { str: Any ->
        println("你传入了：$str")
        str
    }
    println(method17(34544))
    println(method17('C'))
    println(method17("DDD"))

    val method19:String.()->Unit={
        println("你是$this")
    }
    "DDD".method19()

    val method20:Int.(Int) ->String={"两数相加结果是${this+it}"}
    println(1.method20(2))
    println(method20(1,2))

    val method21:Double.(Double,Double)->Unit = {d1,d2-> println("三数相加${this+d1+d2}")}
    method21(55.1,33.2,111.1)
    method21.invoke(55.5,6.6,77.7)
    55.5.method21(55.6,666.4)

    val method22:Char.(String) ->Unit={
        println(if (this =='男') "先生你好" else if (this =='女') "女士你好" else it)
    }
    'A'.method22("未知人类")
    method22('女',"未知人类")


    fun Char.meshod23(default:String){
        println(if (this=='男')"先生你好" else if (this=='女')"女士你好" else default)
    }
    '男'.meshod23("未知人类")
    // TODO 我们前面一直在玩参数输入，现在我们玩输出（返回实现）

    fun t01(){ println(1)}//默认Unit,除非指定类型
    fun t02(){54656.45}//默认Unit
    fun t03(){true} //默认Unit
    fun t04():String{return  "124"}
//    println(t04())
    fun t05():Int{return 99}//在函数体里面 return xxx，是无法类型推到的
    fun s01() ={}
    fun s02()={ println("Ok")}
    // // s03和s04都有入参的时候要怎么调用
    // run { 执行你的函数 k02.show1 k02.show2  }
    fun s03():Boolean = run{true}// Boolean    run返回 {}里面的函数返回类型
    fun s04():()->Boolean={true}// () -> Boolean    输入 -> 输出
    s03()
    s04()()

    fun k01()={n1:Int-> println("你输入的是int${if(n1 is Int) "你是Int类型:$n1"  else "你不是Int"}")}
    k01()(88)

    fun k02():(Int,Int)->Char={n1:Int,n2:Int-> println("两数相加${n1+n2}")
        true
        "STTT"
        'A'
    }// 划重点，想写多行直接敲回车，为什么要换行：为了编译器检查
    k02()(1,3)

    val methodx1:(String)->Int = fun(str):Int{
        return str.length // 不是之前学校的lambda体，这个方法体，需要写完return
    }
    //一般开发不会用fun关键字+声明处

    val methodx2 = { str:String -> str.length}

    val methodx3 :Function1<String,Int> ={
        str:String->
        str.length
    }
    println(methodx3("12345"))
    val methodx4: Function2<Boolean,String,Unit> ={
        isOk:Boolean,str:String -> println("isOk:$isOk")
    }
    methodx4(true,"666")

    var age:Int = 19
    fun aa(){}
    val aa2={}
    // aa就是一个函数，实打实的函数
    // aa2 是接收一个匿名函数的变量而已，这个变量 可以执行这个匿名函数
    // 共同点：他们现象是一样的
    var aa3 = aa2 // 都属于函数引用的概念

    var aa4 = ::aa // 实打实的函数 变成 函数引用 所以可以传递赋值 给另外一个变量
    // 前面为什么用var方法不应该是fun吗？
    // 我们一直在写匿名函数，把匿名函数给 method01 变量
    // KT函数是一等公民

    // 全栈语言： 服务器，iOS，Android，Windows，JS，Gradle Groovy  build.gradle.kts ...
    // native层

    // 函数中的函数，就是高阶函数

    // KT中的 基本上都是表达式 包括 if  可以灵活返回
    // Java中，基本上都是 语句 包括 if  执行体 不可以返回
    var a = if (true) 111 else 222

    66.toast()
    true.toast()
}

fun Any.toast(){
    println("你个货调用了我，你的值是:$this")
}